障害注入の自動化を目指してGremlin APIを使ってみた
こんにちは。AWS事業本部のKyoです。
みなさま、自動化はお好きでしょうか?カオスエンジニアリングにおいても自動化は重要なトピックの1つです。
今回はGetting started with Gremlin’s APIを元にAPIから障害注入を行ってみました。APIから障害注入を行うことでCI/CDとの統合が可能になり、障害注入の自動化が可能になります。
概要
今回は以下の2つを行っています。
- GUIから簡単にAPIの実行コマンドを取得する
- CLIから障害注入をやってみる
準備
- Gremlinアカウント(
CompanyName
,Team ID
,Secret Key
が必要) - Gremlin agentがインストールされたEC2インスタンス x1
各種情報の取得方法やGremlin agentのインストール、GUIからの障害注入のは方法などは以下のブログをご覧ください。
GUIから簡単にAPIの実行コマンドを取得する
curlを利用してAPIを叩くことは多いと思いますが、パラメータの設定等に手間取ることは少なくないのではないでしょうか。Gremlinのコンソールをポチポチするだけで、APIの実行コマンドが簡単に生成できます。
API実行コマンドの取得
まず、Gremlinのコンソールにログインし、左カラムよりAttacks
を選択します。
通常の攻撃と同様に対象と注入する障害を選択します。
Choose Hosts to target
から準備していたインスタンスを選択し、Choose a Gremlin
からCPU攻撃を120秒としました。
通常ならば、ここでUnleash Gremlin
のボタンをクリックするところですが、今回はその右側のGremlin API Examples
をクリックします。
すると、以下の画面が表示されるので、CURL Example
の右のCopy to clipboad
をクリックします。
以下のコマンドがクリップボードにコピーできました。
これを実行することで、先ほど選択した内容の障害注入を実施できます。パラメータにもCPU
や120
という文字列が確認できます。
curl -i -X POST 'https://api.gremlin.com/v1/attacks/new?teamId=<your team id>' \ -H 'Content-Type: application/json;charset=utf-8' \ -H 'Authorization: <your bearer>' \ -d '{"target":{"hosts":{"ids":["10.0.1.82"]},"type":"Exact"},"command":{"type":"cpu","commandType":"CPU","args":["-l","120","-c","1"]}}'
同様の方法で、CPU攻撃以外についてもGUIからAPIの実行コマンドを生成することが可能です。
障害注入の実施と確認
障害注入を実行し、確認します。 Activeとして表示されています。
詳細を表示します。
念のため、対象のEC2にもログインしtop
コマンドを実行してみました。
gremlinによってCPUリソースが消費されていることが確認できました。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2637 gremlin 20 0 23400 5872 5500 S 99.3 0.6 1:00.27 gremlin 1 root 20 0 159820 8928 6568 S 0.0 0.9 0:02.77 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp 5 root 20 0 0 0 0 I 0.0 0.0 0:00.07 kworker/0:0-eve 〜〜以下略〜〜
CLIから障害注入をやってみる
自動化のためには一連の動作がCLIで完結する必要があります。
認証
以下のコマンドでBearer
を取得します。
curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'email=gremlin@gremlin.com' \ --data-urlencode 'password=P@ssw0rd1!' \ --data-urlencode 'companyName=Chaos' \ 'https://api.gremlin.com/v1/users/auth'
コンソールへのログインにMFAを利用している場合は、下記のように-data-urlencode
が必要です。
curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'email=gremlin@gremlin.com' \ --data-urlencode 'password=changeit' \ --data-urlencode 'token=000000' \ 'https://api.gremlin.com/v1/users/auth/mfa/auth?getCompanySession=true'
レスポンスとして以下のようなJSONが返ってきます(一部の結果はダミーです)。
[ { "company_id": "<company_id>", "company_is_alfi_enabled": true, "expires_at": "2020-07-17T01:58:15.357Z", "header": "Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "identifier": "<email>", "org_id": "<org_id>", "org_name": "<org_name>", "renew_token": "<renew_token>", "token": "<token>", "tier": "Enterprise", "roles": [ "<role1>", "<role2>" ], "privileges": [ "<privileges1>", "<privileges2>" ], "company_name": "<company_name>", "last_login": "2020-06-21T09:28:53.820Z" } ]
所属している組織の数だけの情報が含まれます。
bearer
を利用するため、header
の値を取得し、変数化しておきます。
export bearertoken="Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
障害注入
先ほどと同様にCPU攻撃を120秒行います。今回ターゲットはランダムにしてあります。
curl -X POST \ --header "Content-Type: application/json" \ --header "Authorization: $bearertoken" \ https://api.gremlin.com/v1/attacks/new?teamId=<your team id> \ --data ' { "command": { "type": "cpu", "args": ["-c", "1", "--length", "120"] }, "target": { "type": "Random" } }'
上記を実行すると実行IDが返されます。これをもとに、障害注入状態の確認を行えます。
障害注入状態の確認
以下のコマンドで障害注入の状態を確認することが可能です。
curl -X GET "https://api.gremlin.com/v1/attacks/<実行ID>?teamId=<your team id>" \ --header "Authorization: $bearertoken" \ -H "accept: application/json"
以下のようなJSONが返されます(一部の結果はダミーです)。
{ "total_clients": 1, "infra_target": { "resolvedHosts": [ "ip-192-168-9-36.ap-northeast-1.compute.internal" ], "targetType": "Host", "strategy": { "allHosts": false, "count": 1, "type": "RandomCount", "allContainers": false }, "strategyType": "Random" }, "client_metrics_enabled_count": 1, "target_type": "Host", "version": 9, "targets": [ "ip-192-168-9-36.ap-northeast-1.compute.internal" ], "org_id": "<org_id>", "args": [ "cpu", "-c", "1", "--length", "120" ], "created_at": "2020-07-16T14:26:27.210Z", "create_source": "Api", "stage": "Successful", "execution_stage_summary": { "Successful": 1 }, "infra_command": { "commandType": "CPU", "commandArgs": { "allCores": false, "cores": 1, "length": 120, "percent": 100 } }, "stage_lifecycle": "Complete", "guid": "<実行ID>", "create_user": "<email>", "start_time": "2020-07-16T14:26:27.210Z", "end_time": "2020-07-16T14:28:40.105Z", "updated_at": "2020-07-16T14:28:40.105Z", "kind": "Api"
念のため、コンソールも見てみます。
こちらでも障害注入の成功が確認できました!
Appendix
APIリファレンスは以下にあります。
おわりに
今回はGremlin APIを利用して、GUIから簡単にAPIの実行コマンドを取得し、CLIから障害注入を実施してみました。
カオスエンジニアリングの原則の詳細原則の1つ、「継続的に実行する検証の自動化」 に一歩近づけたのではないでしょうか。
手作業による検証は、手間がかかり、最終的には長続きしません。実験を自動化し、継続して実行します。カオスエンジニアリングは、オーケストレーションと分析の両方を行うためにシステムを自動化します。
以上、何かのお役に立てれば幸いです。